package com.syh.jn.scm.infrastructure.repository.utils;

import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.util.reflection.ExtReflectionUtils;
import com.google.common.base.CaseFormat;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by soci.song on 2018/9/9.
 */
public class SQLAliasGenerateUtil {
    private static final String AS = " AS ";

    /**
     *  实体属性生成别名
     * @param clazz
     * @param tableAlias from table 的 表别名
     * @param coulmnAlias 需要生成的字段别名前缀
     * @return
     */
    public static String aliasGenerate(Class clazz,String tableAlias,String coulmnAlias){
        List<String> coulmns = ExtReflectionUtils.findFieldsName(clazz);
        return aliasJoin(coulmns,tableAlias,coulmnAlias);
    }

    /**
     * 多个实体属性生成别名
     * @param clazz
     * @param tableAliases
     * @param coulmnAliases
     * @return
     */
    public static String aliasGenerate(Class[] clazz,String[] tableAliases,String[] coulmnAliases){
        List<List<String>> columns = new ArrayList<>();
        Arrays.asList(clazz).stream()
                .forEach(c ->{
                   columns.add(ExtReflectionUtils.findFieldsName(c));
                });
        return aliasJoin(columns,tableAliases,coulmnAliases);
    }

    /**
     * 实体属性生成别名
     * @param clazz
     * @param tableAlias
     * @param coulmnAlias
     * @param excludes 不需要生成别名的属性，如：级联对象
     * @return
     */
    public static String aliasGenerate(Class clazz,String tableAlias,String coulmnAlias,String[] excludes){
        if(excludes.length == 0){
            throw new IllegalArgumentException("The excludes of param comp isn't available.");
        }
        List<String> coulmns = ExtReflectionUtils.findFieldsName(clazz,excludes);
        return aliasJoin(coulmns,tableAlias,coulmnAlias);
    }

    /**
     * 多个实体属性生成别名
     * @param clazz
     * @param tableAliases
     * @param coulmnAliases
     * @param excludes 不需要生成别名的属性，如：级联对象 注：下标对应class数组的下标
     * @return
     */
    public static String aliasGenerate(Class[] clazz,String[] tableAliases,String[] coulmnAliases,String[][] excludes){
        List<List<String>> columns = new ArrayList<>();
        for (int i = 0; i < clazz.length; i++) {
            if (i >= excludes.length) {
                columns.add(ExtReflectionUtils.findFieldsName(clazz[i]));
            } else {
                columns.add(ExtReflectionUtils.findFieldsName(clazz[i], excludes[i]));
            }
        }
        return aliasJoin(columns,tableAliases,coulmnAliases);
    }

    /**
     * 拼接别名
     * @param coulmns
     * @param tableAlias
     * @param coulmnAlias
     * @return
     */
    private static String aliasJoin(List<String> coulmns,String tableAlias,String coulmnAlias){
        StringBuffer sb = new StringBuffer();
        coulmns.stream()
                .map(s -> {
                    StringBuffer str = new StringBuffer();
                    str.append(ExtStringUtils.isEmpty(tableAlias)?"":tableAlias+".").append(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, s))
                            .append(AS).append("'").append(ExtStringUtils.isEmpty(coulmnAlias)?"":coulmnAlias+".").append(s).append("',");
                    return str.toString();
                }).forEach(s -> sb.append(s));
        return sb.deleteCharAt(sb.length()-1).toString();
    }

    /**
     * 多个实体拼接别名
     * @param coulmns
     * @param tableAliases
     * @param coulmnAliases
     * @return
     */
    private static String aliasJoin(List<List<String>> coulmns,String[] tableAliases,String[] coulmnAliases){
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < coulmns.size(); i++) {
            String tAlias = "";
            String cAlias = "";
            if ( tableAliases!= null && i < tableAliases.length) {
                tAlias = tableAliases[i];
            }
            if ( coulmnAliases!= null && i < coulmnAliases.length) {
                cAlias = coulmnAliases[i];
            }
            List<String> clms = coulmns.get(i);
            String finalTAlias = tAlias;
            String finalCAlias = cAlias;
            clms.stream()
                    .map(s -> {
                        StringBuffer str = new StringBuffer();
                        str.append(ExtStringUtils.isEmpty(finalTAlias)?"": finalTAlias +".").append(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, s))
                                .append(AS).append("'").append(ExtStringUtils.isEmpty(finalCAlias)?"": finalCAlias +".").append(s).append("',");
                        return str.toString();
                    }).forEach(s -> sb.append(s));
        }
        return sb.deleteCharAt(sb.length()-1).toString();
    }
}
